package com.example.chamberlainserver.Service.impl;

import com.example.chamberlainserver.Entry.Material;
import com.example.chamberlainserver.Entry.MaterialBorrowRecord;
import com.example.chamberlainserver.Service.MaterialBorrowRecordService;
import com.example.chamberlainserver.Service.MaterialService;
import com.example.chamberlainserver.Vo.Request.Material.MaterialBorrowDTO;
import com.example.chamberlainserver.Vo.Request.Material.MaterialBorrowQuery;
import com.example.chamberlainserver.dto.PageResult;
import com.example.chamberlainserver.mapper.MaterialBorrowRecordMapper;
import com.example.chamberlainserver.mapper.MaterialMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 物资外借记录服务实现类
 */
@Service
public class MaterialBorrowRecordServiceImpl implements MaterialBorrowRecordService {

    @Autowired
    private MaterialBorrowRecordMapper materialBorrowRecordMapper;
    
    @Autowired
    private MaterialMapper materialMapper;
    
    @Autowired
    private MaterialService materialService;
    
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 添加物资外借记录
     * @param borrowDTO 物资外借记录DTO
     * @return 添加后的物资外借记录
     */
    @Override
    @Transactional
    public MaterialBorrowRecord addBorrowRecord(MaterialBorrowDTO borrowDTO) {
        // 验证物资外借记录信息
        validateBorrowRecord(borrowDTO);
        
        // 检查物资是否存在
        Material material = materialMapper.getMaterialById(borrowDTO.getMaterialId());
        if (material == null) {
            throw new IllegalArgumentException("物资不存在");
        }
        
        // 检查借用数量是否超过库存
        if (borrowDTO.getBorrowQuantity() > material.getQuantity()) {
            throw new IllegalArgumentException("借用数量超过库存数量");
        }
        
        // 创建物资外借记录
        MaterialBorrowRecord record = convertToEntity(borrowDTO);
        record.setIsReturned(false); // 新增时默认未归还
        record.setCreateTime(LocalDateTime.now());
        record.setUpdateTime(LocalDateTime.now());
        
        // 插入物资外借记录
        materialBorrowRecordMapper.insertBorrowRecord(record);
        
        // 更新物资库存
        int newQuantity = material.getQuantity() - borrowDTO.getBorrowQuantity();
        materialService.updateMaterialStock(material.getId(), newQuantity);
        
        return record;
    }

    /**
     * 更新物资外借记录
     * @param borrowDTO 物资外借记录DTO
     * @return 更新后的物资外借记录
     */
    @Override
    @Transactional
    public MaterialBorrowRecord updateBorrowRecord(MaterialBorrowDTO borrowDTO) {
        // 检查记录是否存在
        MaterialBorrowRecord existingRecord = materialBorrowRecordMapper.getBorrowRecordById(borrowDTO.getId());
        if (existingRecord == null) {
            throw new IllegalArgumentException("物资外借记录不存在");
        }
        
        // 如果已归还，不允许修改
        if (existingRecord.getIsReturned()) {
            throw new IllegalArgumentException("已归还的物资外借记录不能修改");
        }
        
        // 验证物资外借记录信息
        validateBorrowRecord(borrowDTO);
        
        // 如果修改了物资ID或借用数量，需要处理库存
        if (!existingRecord.getMaterialId().equals(borrowDTO.getMaterialId()) ||
            !existingRecord.getBorrowQuantity().equals(borrowDTO.getBorrowQuantity())) {
            
            // 先恢复原物资库存
            Material oldMaterial = materialMapper.getMaterialById(existingRecord.getMaterialId());
            if (oldMaterial != null) {
                int oldNewQuantity = oldMaterial.getQuantity() + existingRecord.getBorrowQuantity();
                materialService.updateMaterialStock(oldMaterial.getId(), oldNewQuantity);
            }
            
            // 再减少新物资库存
            Material newMaterial = materialMapper.getMaterialById(borrowDTO.getMaterialId());
            if (newMaterial == null) {
                throw new IllegalArgumentException("物资不存在");
            }
            
            // 检查借用数量是否超过库存
            if (borrowDTO.getBorrowQuantity() > newMaterial.getQuantity()) {
                throw new IllegalArgumentException("借用数量超过库存数量");
            }
            
            int newQuantity = newMaterial.getQuantity() - borrowDTO.getBorrowQuantity();
            materialService.updateMaterialStock(newMaterial.getId(), newQuantity);
        }
        
        // 更新物资外借记录
        MaterialBorrowRecord record = convertToEntity(borrowDTO);
        record.setIsReturned(existingRecord.getIsReturned());
        record.setUpdateTime(LocalDateTime.now());
        
        materialBorrowRecordMapper.updateBorrowRecord(record);
        
        return materialBorrowRecordMapper.getBorrowRecordById(record.getId());
    }

    /**
     * 删除物资外借记录
     * @param id 记录ID
     * @return 是否删除成功
     */
    @Override
    @Transactional
    public boolean deleteBorrowRecord(Long id) {
        // 检查记录是否存在
        MaterialBorrowRecord existingRecord = materialBorrowRecordMapper.getBorrowRecordById(id);
        if (existingRecord == null) {
            return false;
        }
        
        // 如果未归还，需要恢复物资库存
        if (!existingRecord.getIsReturned()) {
            Material material = materialMapper.getMaterialById(existingRecord.getMaterialId());
            if (material != null) {
                int newQuantity = material.getQuantity() + existingRecord.getBorrowQuantity();
                materialService.updateMaterialStock(material.getId(), newQuantity);
            }
        }
        
        // 删除物资外借记录
        int rows = materialBorrowRecordMapper.deleteBorrowRecord(id);
        
        return rows > 0;
    }

    /**
     * 根据ID查询物资外借记录
     * @param id 记录ID
     * @return 物资外借记录
     */
    @Override
    public MaterialBorrowRecord getBorrowRecordById(Long id) {
        return materialBorrowRecordMapper.getBorrowRecordById(id);
    }

    /**
     * 分页查询物资外借记录
     * @param query 查询条件
     * @return 分页结果
     */
    @Override
    public PageResult<MaterialBorrowRecord> pageBorrowRecords(MaterialBorrowQuery query) {
        // 参数校验
        if (query == null) {
            throw new IllegalArgumentException("查询参数不能为空");
        }
        
        // 分页参数
        Integer current = query.getCurrent();
        Integer pageSize = query.getPageSize();
        if (current == null || current < 1) {
            current = 1;
        }
        if (pageSize == null || pageSize < 1) {
            pageSize = 10;
        }
        
        // 计算偏移量
        int offset = (current - 1) * pageSize;
        
        // 查询数据
        List<MaterialBorrowRecord> records = materialBorrowRecordMapper.pageBorrowRecords(query, offset, pageSize);
        long total = materialBorrowRecordMapper.countBorrowRecords(query);
        
        // 构建分页结果
        return new PageResult<>(current, pageSize, total, records);
    }

    /**
     * 归还物资
     * @param id 记录ID
     * @param isIntact 是否完好
     * @param remark 备注
     * @return 更新后的物资外借记录
     */
    @Override
    @Transactional
    public MaterialBorrowRecord returnMaterial(Long id, Boolean isIntact, String remark) {
        // 检查记录是否存在
        MaterialBorrowRecord existingRecord = materialBorrowRecordMapper.getBorrowRecordById(id);
        if (existingRecord == null) {
            throw new IllegalArgumentException("物资外借记录不存在");
        }
        
        // 如果已归还，不允许重复归还
        if (existingRecord.getIsReturned()) {
            throw new IllegalArgumentException("物资已归还，不能重复归还");
        }
        
        // 更新物资外借记录
        existingRecord.setIsReturned(true);
        existingRecord.setIsIntact(isIntact);
        existingRecord.setReturnTime(LocalDateTime.now());
        existingRecord.setRemark(remark);
        existingRecord.setUpdateTime(LocalDateTime.now());
        
        materialBorrowRecordMapper.updateBorrowRecord(existingRecord);
        
        // 如果物资完好，恢复物资库存
        if (isIntact) {
            Material material = materialMapper.getMaterialById(existingRecord.getMaterialId());
            if (material != null) {
                int newQuantity = material.getQuantity() + existingRecord.getBorrowQuantity();
                materialService.updateMaterialStock(material.getId(), newQuantity);
            }
        }
        
        return materialBorrowRecordMapper.getBorrowRecordById(id);
    }
    
    /**
     * 验证物资外借记录信息
     * @param borrowDTO 物资外借记录DTO
     */
    private void validateBorrowRecord(MaterialBorrowDTO borrowDTO) {
        // 验证物资ID
        if (borrowDTO.getMaterialId() == null) {
            throw new IllegalArgumentException("物资ID不能为空");
        }
        
        // 验证借用人姓名
        if (borrowDTO.getBorrowerName() == null || borrowDTO.getBorrowerName().trim().isEmpty()) {
            throw new IllegalArgumentException("借用人姓名不能为空");
        }
        
        // 验证借用人电话
        if (borrowDTO.getBorrowerPhone() == null || borrowDTO.getBorrowerPhone().trim().isEmpty()) {
            throw new IllegalArgumentException("借用人电话不能为空");
        }
        
        // 验证用途
        if (borrowDTO.getPurpose() == null || borrowDTO.getPurpose().trim().isEmpty()) {
            throw new IllegalArgumentException("用途不能为空");
        }
        
        // 验证借用数量
        if (borrowDTO.getBorrowQuantity() == null || borrowDTO.getBorrowQuantity() <= 0) {
            throw new IllegalArgumentException("借用数量必须大于0");
        }
        
        // 验证借用时间
        if (borrowDTO.getBorrowTime() == null || borrowDTO.getBorrowTime().trim().isEmpty()) {
            throw new IllegalArgumentException("借用时间不能为空");
        }
    }
    
    /**
     * 将DTO转换为实体
     * @param borrowDTO 物资外借记录DTO
     * @return 物资外借记录实体
     */
    private MaterialBorrowRecord convertToEntity(MaterialBorrowDTO borrowDTO) {
        MaterialBorrowRecord record = new MaterialBorrowRecord();
        record.setId(borrowDTO.getId());
        record.setMaterialId(borrowDTO.getMaterialId());
        record.setMaterialName(borrowDTO.getMaterialName());
        record.setBorrowerName(borrowDTO.getBorrowerName());
        record.setBorrowerPhone(borrowDTO.getBorrowerPhone());
        record.setBorrowerClass(borrowDTO.getBorrowerClass());
        record.setPurpose(borrowDTO.getPurpose());
        record.setBorrowQuantity(borrowDTO.getBorrowQuantity());
        record.setBorrowTime(LocalDateTime.parse(borrowDTO.getBorrowTime(), DATE_TIME_FORMATTER));
        
        if (borrowDTO.getReturnTime() != null && !borrowDTO.getReturnTime().trim().isEmpty()) {
            record.setReturnTime(LocalDateTime.parse(borrowDTO.getReturnTime(), DATE_TIME_FORMATTER));
        }
        
        record.setIsReturned(borrowDTO.getIsReturned());
        record.setIsIntact(borrowDTO.getIsIntact());
        record.setBorrowOperatorId(borrowDTO.getBorrowOperatorId());
        record.setRemark(borrowDTO.getRemark());
        
        return record;
    }
}